﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using ITLlib;
using eSSP_example.Services;
using eSSP_example.Cpi;
using System.ServiceModel.Web;
using eSSP_example.Classes;
using eSSP_example.Utilities;

namespace eSSP_example
{
    public partial class frmMain : Form
    {
        CashGenicService service;
        WebServiceHost _serviceHost;

        //  Variables
        public bool cpiRunning = false, payoutRunning = false;
        volatile public bool cpiConnecting = false, payoutConnecting = false;

        int pollTimer = 250; // timer in ms
        CCpi    cpiHopper;
        CPayout Payout; // The class that interfaces with the Payout
        
        bool FormSetup = false; // To ensure the form is only set up on first run
        frmPayoutByDenom payoutByDenomFrm; // Payout by denomination form
        
        delegate void OutputMessage(string msg); // Delegate for invoking on cross thread calls 
        Thread tCpiRec, tSPRec; // Handles to each of the reconnection threads for the 2 units
        
        //  Constructor
        public frmMain()
        {
            InitializeComponent();
            
            timer1.Interval = pollTimer;
            timer2.Interval = 500; // update UI every 500ms
            
            this.Location = new Point(Screen.PrimaryScreen.Bounds.X + 50, Screen.PrimaryScreen.Bounds.Y + 30);
            this.Enabled = false;
        }

        //  This updates UI variables such as textboxes etc.
        void    UpdateUI()
        {
            //  Get stored notes info from SMART Payout and Cpi Hopper at intervals
            if  (!timer2.Enabled)
            {
                tbChannelLevels.Text =  Payout.GetChannelLevelInfo();

                tbCoinLevels.Text    =  cpiHopper.GetChannelLevelInfo();

                timer2.Enabled = true;
            }
        }

        //  The main program loop, this is to control the validator, it polls at
        //  a value set in this class (pollTimer).
        public void MainLoop()
        {
            this.Enabled = true;
            btnRun.Enabled = false;
            btnHalt.Enabled = true;

            //  Connect to the validators (non-threaded for initial connect)
            ConnectToSMARTPayout(textBox1);
            ConnectToCpiHopper(textBox1);

            //  Enable validators
            Payout.EnableValidator();
            cpiHopper.EnableValidator();

            //  While app active
            while (!CHelpers.Shutdown)
            {
                //  Setup form layout on first run
                if (!FormSetup)
                {
                    SetupFormLayout();
                    
                    FormSetup = true;
                }

                //  If the Hopper is supposed to be running but the poll fails
                if  (cpiRunning && !cpiConnecting && !cpiHopper.DoPoll(textBox1))
                {
                    textBox1.AppendText("Lost connection to Cpi Hopper\r\n");
                    
                    //  If the other unit isn't running, refresh the port by closing it
                    //if  (!payoutRunning) LibraryHandler.ClosePort();
                    //cpiRunning = false;
                    
                    //  Create and start a reconnection thread, this allows this loop to continue executing
                    //  and polling the other validator
                    tCpiRec = new Thread(() => ReconnectCpiHopper());
                    tCpiRec.Start();
                }

                //  Same as above but for the Payout
                if  (payoutRunning && !payoutConnecting && !Payout.DoPoll(textBox1))
                {
                    textBox1.AppendText("Lost connection to SMART Payout\r\n");
                    
                    // If the other unit isn't running, refresh the port by closing it
                    //if (!hopperRunning) LibraryHandler.ClosePort();
                    //payoutRunning = false;
                    
                    //  Create and start a reconnection thread, this allows this loop to continue executing
                    //  and polling the other validator
                    tSPRec = new Thread(() => ReconnectPayout());
                    tSPRec.Start();
                }

                UpdateUI();

                timer1.Enabled = true;
                while (timer1.Enabled) Application.DoEvents();
            }

            btnRun.Enabled = true;
            btnHalt.Enabled = false;
        }

        //  This is a one off function that is called the first time the MainLoop()
        //  function runs, it just sets up a few of the UI elements that only need
        //  updating once.
        private void SetupFormLayout()
        {
            //  Get channel levels in hopper
            tbCoinLevels.Text = cpiHopper.GetChannelLevelInfo();

            //  setup list of recyclable channel tick boxes based on OS type
            System.OperatingSystem osInfo = System.Environment.OSVersion;
            int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
            
            //  XP, 2000, Server 2003
            if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version.Major == 5)
            {
                x1 = this.Location.X + 455 - 200;
                y1 = this.Location.Y + 10 + 400;
                x2 = this.Location.X + 780 - 120;
                y2 = this.Location.Y + 10 + 400;
            }
            
            //  Vista, 7
            else if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version.Major == 6)
            {
                x1 = this.Location.X + 458 - 200;
                y1 = this.Location.Y + 12 + 400;
                x2 = this.Location.X + 780 - 120;
                y2 = this.Location.Y + 12 + 400;
            }

            GroupBox g1 = new GroupBox();
            g1.Size = new Size(120, 380);
            g1.Location = new Point(x1, y1);
            g1.Text = "Cpi Recycling";

            GroupBox g2 = new GroupBox();
            g2.Size = new Size(120, 380);
            g2.Location = new Point(x2, y2);
            g2.Text = "Payout Recycling";

            //  Hopper checkboxes
            for (int i = 1; i <= cpiHopper.NumberOfChannels; i++)
            {
                CheckBox c = new CheckBox();

                c.Location = new Point(5 + 10, 20 + (i * 20));
                c.Name = i.ToString();
                c.Text = CHelpers.FormatToCurrency(cpiHopper.GetChannelValue(i)) + " " + new String(cpiHopper.GetChannelCurrency(i));
                //c.Checked = cpiHopper.IsChannelRecycling(i);
                c.Checked = true;
                //c.CheckedChanged += new EventHandler(recycleBoxHopper_CheckedChange);

                g1.Controls.Add(c);
            }

            //  Payout checkboxes
            for (int i = 1; i <= Payout.NumberOfChannels; i++)
            {
                CheckBox c = new CheckBox();
                c.Location = new Point(5 + 10, 20 + (i * 20));
                c.Name = i.ToString();
                
                ChannelData d = new ChannelData();

                Payout.GetDataByChannel(i, ref d);
                c.Text = CHelpers.FormatToCurrency(d.Value) + " " + new String(d.Currency);
                c.Checked = d.Recycling;
                c.CheckedChanged += new EventHandler(recycleBoxPayout_CheckedChange);
                g2.Controls.Add(c);
            }

            Controls.Add(g1);
            Controls.Add(g2);
        }

        /// <summary>
        ///     ConnectToCpiHopper
        /// </summary>
        /// <param name="log"></param>
        public void ConnectToCpiHopper(TextBox log = null)
        {
            cpiConnecting = true;

            //  setup timer, timeout delay and number of attempts to connect
            System.Windows.Forms.Timer reconnectionTimer = new System.Windows.Forms.Timer();
            reconnectionTimer.Tick += new EventHandler(reconnectionTimer_Tick);
            reconnectionTimer.Interval = 1000; // ms
            int attempts = 10;

            //  Setup connection info
            //  Run for number of attempts specified
            for (int i = 0; i < attempts; i++)
            {
                if (log != null)
                {
                    log.AppendText("==========================================\r\n");
                    log.AppendText("Trying connection to Cpi Hopper\r\n");
                }

                //  if the key negotiation is successful then set the rest up
                if  (cpiHopper.OpenPort())
                {
                    //  get info from the hopper and store useful vars
                    cpiHopper.HopperSetupRequest(log);

                    //  check the right unit is connected
                    if  (!IsHopperSupported(cpiHopper.UnitType))
                    {
                        MessageBox.Show("Unsupported type shown by Cpi Hopper, this SDK supports the SMART Payout and the Cpi Hopper only");
                        cpiConnecting = false;

                        Application.Exit();
                        return;
                    }

                    //  inhibits, this sets which channels can receive coins
                    cpiHopper.SetInhibits(log);

                    //  Get serial number.
                    cpiHopper.GetSerialNumber(textBox1);

                    // set running to true so the hopper begins getting polled
                    cpiRunning = true;
                    cpiConnecting = false;
                    return;
                }

                //  reset timer
                reconnectionTimer.Enabled = true;
                while (reconnectionTimer.Enabled)
                {
                    if (CHelpers.Shutdown)
                    {
                        cpiConnecting = false;
                        return;
                    }

                    Application.DoEvents();
                    Thread.Sleep(1);
                }
            }

            cpiConnecting = false;
            return;
        }      

        /// <summary>
        ///     ConnectToSMARTPayout
        /// </summary>
        /// <param name="log"></param>
        public void ConnectToSMARTPayout(TextBox log = null)
        {
            payoutConnecting = true;

            //  setup timer, timeout delay and number of attempts to connect
            System.Windows.Forms.Timer reconnectionTimer = new System.Windows.Forms.Timer();
            reconnectionTimer.Tick += new EventHandler(reconnectionTimer_Tick);
            reconnectionTimer.Interval = 1000; // ms
            int attempts = 10;

            //  Setup connection info
            Payout.CommandStructure.ComPort = Global.ValidatorComPort;
            Payout.CommandStructure.SSPAddress = Global.Validator1SSPAddress;
            Payout.CommandStructure.BaudRate = 9600;
            Payout.CommandStructure.Timeout = 1000;
            Payout.CommandStructure.RetryLevel = 3;

            //  Run for number of attempts specified
            for (int i = 0; i < attempts; i++)
            {
                if (log != null) log.AppendText("Trying connection to SMART Payout\r\n");

                //  turn encryption off for first stage
                Payout.CommandStructure.EncryptionStatus = false;

                //  Open port first, if the key negotiation is successful then set the rest up
                if  (Payout.OpenPort() && Payout.NegotiateKeys(log))
                {
                    Payout.CommandStructure.EncryptionStatus = true; // now encrypting
                    
                    //  find the max protocol version this validator supports
                    byte maxPVersion = FindMaxPayoutProtocolVersion();
                    if (maxPVersion >= 6)
                        Payout.SetProtocolVersion(maxPVersion, log);
                    else
                    {
                        MessageBox.Show("This program does not support units under protocol 6!", "ERROR");
                        payoutConnecting = false;
                        return;
                    }

                    //  get info from the validator and store useful vars
                    Payout.PayoutSetupRequest(log);
                    
                    //  check the right unit is connected
                    if  (!IsValidatorSupported(Payout.UnitType))
                    {
                        MessageBox.Show("Unsupported type shown by SMART Payout, this SDK supports the SMART Payout and the SMART Hopper only");
                        payoutConnecting = false;

                        Application.Exit();
                        return;
                    }

                    //  inhibits, this sets which channels can receive notes
                    Payout.SetInhibits(log);
                    
                    //  Get serial number.
                    Payout.GetSerialNumber(log);
                    
                    //  enable payout
                    Payout.EnablePayout(log);
                    
                    //  set running to true so the validator begins getting polled
                    payoutRunning = true;
                    payoutConnecting = false;
                    return;
                }

                //  reset timer
                reconnectionTimer.Enabled = true;
                while (reconnectionTimer.Enabled)
                {
                    if  (CHelpers.Shutdown)
                    {
                        payoutConnecting = false;
                        return;
                    }

                    Application.DoEvents();
                    Thread.Sleep(1);
                }
            }

            payoutConnecting = false;
            return;
        }

        //  Used when invoking for cross-thread calls
        private void AppendToTextBox(string s)
        {
            textBox1.AppendText(s);
        }

        //  These functions are run in a seperate thread to allow
        //  the main loop to continue executing.
        /// <summary>
        ///     ReconnectCpiHopper
        /// </summary>
        private void ReconnectCpiHopper()
        {
            OutputMessage m = new OutputMessage(AppendToTextBox);

            while (!cpiRunning)
            {
                if (textBox1.InvokeRequired)
                    textBox1.Invoke(m, new object[] { "Attempting to reconnect to Cpi Hopper...\r\n" });
                else
                    textBox1.AppendText("Attempting to reconnect to Cpi Hopper...\r\n");

                ConnectToCpiHopper();

                CHelpers.Pause(1000);

                if (CHelpers.Shutdown) return;
            }
            
            if  (textBox1.InvokeRequired)
                textBox1.Invoke(m, new object[] { "Reconnected to SMART Hopper\r\n" });
            else
                textBox1.AppendText("Reconnected to SMART Hopper\r\n");
            
            cpiHopper.EnableValidator();
        }

        /// <summary>
        ///     ReconnectPayout
        /// </summary>
        private void ReconnectPayout()
        {
            OutputMessage m = new OutputMessage(AppendToTextBox);

            while (!payoutRunning)
            {
                if (textBox1.InvokeRequired)
                    textBox1.Invoke(m, new object[] { "Attempting to reconnect to SMART Payout...\r\n" });
                else
                    textBox1.AppendText("Attempting to reconnect to SMART Payout...\r\n");

                ConnectToSMARTPayout(null); // Have to pass null as can't update text box from a different thread without invoking

                CHelpers.Pause(1000);
                if  (CHelpers.Shutdown) return;
            }

            if  (textBox1.InvokeRequired)
                textBox1.Invoke(m, new object[] { "Reconnected to SMART Payout\r\n" });
            else
                textBox1.AppendText("Reconnected to SMART Payout\r\n");

            Payout.EnableValidator();
        }

        /// <summary>
        ///     FindMaxPayoutProtocolVersion
        /// </summary>
        /// <returns></returns>
        private byte FindMaxPayoutProtocolVersion()
        {
            // not dealing with protocol under level 6
            // attempt to set in validator

            byte b = 0x06;

            while (true)
            {
                Payout.SetProtocolVersion(b);

                // If it fails then it can't be set so fall back to previous iteration and return it
                if (Payout.CommandStructure.ResponseData[0] == CCommands.SSP_RESPONSE_FAIL)
                    return --b;
                b++;

                // If the protocol version 'runs away' because of a drop in comms. Return the default value.
                if (b > 20)
                    return 0x06;
            }
        }

        // This function shows a simple example of calculating a payout split between the SMART Payout and the 
        // SMART Hopper. It works on a highest value split, first the notes are looked at, then any remainder
        // that can't be paid out with a note is paid from the SMART Hopper.
        private void CalculatePayout(string amount, char[] currency)
        {
            float payoutAmount;

            try
            {
                // Parse it to a number
                payoutAmount = float.Parse(amount) * 100;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            int payoutList = 0;

            // Obtain the list of sorted channels from the SMART Payout, this is sorted by channel value
            // - lowest first
            List<ChannelData> reverseList = new List<ChannelData>(Payout.UnitDataList);
            reverseList.Reverse(); // Reverse the list so the highest value is first

            // Iterate through each
            foreach(ChannelData d in reverseList)
            {
                ChannelData temp = d; // Don't overwrite real values

                // Keep testing to see whether we need to payout this note or the next note
                while (true)
                {
                    // If the amount to payout is greater than the value of the current note and there is
                    // some of that note available and it is the correct currency
                    if (payoutAmount >= temp.Value && temp.Level > 0 && String.Equals(new String(temp.Currency), new String(currency)))
                    {
                        payoutList += temp.Value; // Add to the list of notes to payout from the SMART Payout
                        payoutAmount -= temp.Value; // Minus from the total payout amount
                        temp.Level--; // Take one from the level
                    }
                    else
                        break; // Don't need any more of this note
                }
            }

            //  Test the proposed payout values
            if  (payoutList > 0)
            {
                // First test SP
                Payout.PayoutAmount(payoutList, currency, true);

                if  (Payout.CommandStructure.ResponseData[0] != 0xF0)
                {
                    DialogResult res =
                        MessageBox.Show("Smart Payout unable to pay requested amount, attempt to pay all from Hopper?",
                        "Error with Payout", MessageBoxButtons.YesNo);

                    if (res == System.Windows.Forms.DialogResult.No)
                        return;
                    else
                        payoutAmount += payoutList;
                }

                // SP is ok to pay
                Payout.PayoutAmount(payoutList, currency, false, textBox1); 
            }

            //  Now if there is any left over, request from Hopper
            if  (payoutAmount > 0)
            {
                //  Test Hopper first
                //cpiHopper.PayoutAmount((int)payoutAmount, currency, true);
                //if (Hopper.CommandStructure.ResponseData[0] != 0xF0)
                //{
                //    MessageBox.Show("Unable to pay requested amount!");
                //    return;
                //}

                //  Hopper is ok to pay
                cpiHopper.PayoutAmount((int)payoutAmount, currency, false, textBox1);
            }
        }

        // This function checks whether the type of validator is supported by this program.
        private bool IsValidatorSupported(char type)
        {
            if  (type == (char)0x06)
                return true;

            return false;
        }

        /// <summary>
        ///     IsHopperSupported
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private bool IsHopperSupported(char type)
        {
            if (type == (char)0x04)
                return  true;

            return  false;
        }

        /* Events handling section */

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            string  strIpAddress;
            string  strServiceAddress;

            //  Create instances of the validator classes
            cpiHopper = new CCpi();
            Payout = new CPayout();

            if  (cpiHopper == null || Payout == null)
            {
                MessageBox.Show("Error with memory allocation, exiting", "ERROR");
                Application.Exit();
            }

            //  Save instance
            ClsGlobalData.getInstance().sPayout     =   Payout;
            ClsGlobalData.getInstance().CpiHopper   =   cpiHopper;

            btnHalt.Enabled = true;

            // Load settings
            logTickBox.Checked = Properties.Settings.Default.Comms;

            // Position comms windows
            Point p = Location;
            p.Y += this.Height;
            //Hopper.Comms.Location = p;
            //p.X += Hopper.Comms.Width;
            Payout.CommsLog.Location = p;

            //------------------Start Web Api----------------------
            //  Web Api 

            strIpAddress = NetworkUtil.getIpV4Address();
            lbl_IpAddress.Text = strIpAddress;

            service = new CashGenicService();
          
            strServiceAddress = "http://" + strIpAddress + ":44333";

            //  Uri baseAddress = new Uri("http://127.0.0.1:44333");
            Uri baseAddress = new Uri(strServiceAddress);

            //  使用新的方式
            _serviceHost = new WebServiceHost(service, baseAddress);

            //  Open Service
            if  (service != null)
            {
                _serviceHost.Open();

                //LogUtils.Info("Service Host Opened", "log");

                MessageBox.Show("Service Host Opened， url = " + strServiceAddress, "OK", MessageBoxButtons.OK);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Shown(object sender, EventArgs e)
        {
            frmOpenMenu f = new frmOpenMenu(this);

            f.Show();
            
            this.Hide();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRun_Click(object sender, EventArgs e)
        {
            textBox1.AppendText("Started poll loop\r\n");

            MainLoop();
        }

        /// <summary>
        ///     Exit App
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form formSettings = new frmSettings();
            formSettings.ShowDialog();

            cpiRunning = false;
            payoutRunning = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer2_Tick(object sender, EventArgs e)
        {
            timer2.Enabled = false;
        }

        /// <summary>
        ///     Halt
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnHalt_Click(object sender, EventArgs e)
        {
            textBox1.AppendText("Poll loop stopped\r\n");

            cpiRunning = false;
            payoutRunning = false;
            
            btnRun.Enabled = true;
            btnHalt.Enabled = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void logTickBox_CheckedChanged(object sender, EventArgs e)
        {
            if  (logTickBox.Checked)
            {
                //  Hopper.Comms.Show();
                Payout.CommsLog.Show();
            }
            else
            {
                //  Hopper.Comms.Hide();
                Payout.CommsLog.Hide();
            }
        }

        /// <summary>
        ///     Form Closing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            cpiRunning = false;
            payoutRunning = false;

            CHelpers.Shutdown = true;
            LibraryHandler.ClosePort();

            Properties.Settings.Default.Comms = logTickBox.Checked;
            Properties.Settings.Default.ComPortVal1 = Global.ValidatorComPort;
            Properties.Settings.Default.SSP1 = Global.Validator1SSPAddress;
            Properties.Settings.Default.SSP2 = Global.Validator2SSPAddress;
            Properties.Settings.Default.Save();

            //  Close 
            cpiHopper.closeApi();

            //  Stop Web Api
            //  Close Service
            if (service != null)
            {
                _serviceHost.Close();

                //  LogUtils.Info("Service Host Closed", "log");

                MessageBox.Show("Service Host Closed");
            }
        }

        /// <summary>
        ///     Do Payout
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPayout_Click(object sender, EventArgs e)
        {
            if (tbPayout.Text != "" && tbPayoutCurrency.Text != "")
                CalculatePayout(tbPayout.Text, tbPayoutCurrency.Text.ToCharArray());
        }

        /// <summary>
        ///     Empty Hopper
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnEmptyHopper_Click(object sender, EventArgs e)
        {
            cpiHopper.EmptyDevice(textBox1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSmartEmptyHopper_Click(object sender, EventArgs e)
        {
            cpiHopper.SmartEmpty(textBox1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnEmptySMARTPayout_Click(object sender, EventArgs e)
        {
            Payout.EmptyPayoutDevice(textBox1);
        }

        /// <summary>
        ///     
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSMARTEmpty_Click(object sender, EventArgs e)
        {
            Payout.SmartEmpty(textBox1);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void recycleBoxHopper_CheckedChange(object sender, EventArgs e)
        {
            CheckBox c = sender as CheckBox;

            try
            {
                //if (c.Checked)
                //    Hopper.RouteChannelToStorage(Int32.Parse(c.Name), textBox1);
                //else
                //    Hopper.RouteChannelToCashbox(Int32.Parse(c.Name), textBox1);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());

                return;
            }
        }

        /// <summary>
        ///     Payout Change Note Route
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void recycleBoxPayout_CheckedChange(object sender, EventArgs e)
        {
            CheckBox chkbox = sender as CheckBox;

            try
            {
                ChannelData d = new ChannelData();

                Payout.GetDataByChannel(Int32.Parse(chkbox.Name), ref d);

                if (chkbox.Checked)
                    Payout.ChangeNoteRoute(d.Value, d.Currency, false, textBox1);
                else
                    Payout.ChangeNoteRoute(d.Value, d.Currency, true, textBox1);

                //  Ensure payout ability is enabled in the validator
                Payout.EnablePayout();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return;
            }
        }

        /// <summary>
        ///     Reset Hopper
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnResetHopper_Click(object sender, EventArgs e)
        {
            cpiHopper.Reset(textBox1);

            // Force reconnect by closing com port
            //CommsLibrary.CloseComPort();
        }

        /// <summary>
        ///     Reset Hopper
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnResetPayout_Click(object sender, EventArgs e)
        {
            Payout.Reset(textBox1);

            // Force reconnect by closing com port
            //CommsLibrary.CloseComPort();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void setLevelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form f = new frmSetLevel(cpiHopper);
            f.Show();
        }

        /// <summary>
        ///     
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void setAllToZeroToolStripMenuItem_Click(object sender, EventArgs e)
        {
            for (int i = 1; i < cpiHopper.NumberOfChannels + 1; i++)
                cpiHopper.SetCoinLevelsByChannel(i, 0, textBox1);

            cpiHopper.UpdateData();
        }

        /// <summary>
        ///     Cpi Pay In
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_CpiPayIn_Click(object sender, EventArgs e)
        {
            float   floatCoinPayIn = 0;
            int     intCoinPayIn = 0;
            bool    parseResult;
            int     result;

            if (tb_CpiPayIn.Text != "")
            {
                parseResult = float.TryParse(tb_CpiPayIn.Text, out floatCoinPayIn);
                if (parseResult)
                {
                    //  Success
                    intCoinPayIn = (int)(floatCoinPayIn * 100);
                    result = ClsApiClass.GetInstance().Cls_AcceptAmount(intCoinPayIn);

                    MessageBox.Show("Cls_AcceptAmount(" + floatCoinPayIn.ToString() + ")" + " call returns : " +
                        ReturnValue.getStrReturnValue(result));
                }
                else
                {
                    //  Success
                    result = ClsApiClass.GetInstance().Cls_AcceptAmount(0);

                    MessageBox.Show("Cls_AcceptAmount(0) call returns : " +
                        ReturnValue.getStrReturnValue(result));
                }
            }
            else
            {
                //  Success
                result = ClsApiClass.GetInstance().Cls_AcceptAmount(0);

                MessageBox.Show("Cls_AcceptAmount(0) call returns : " +
                    ReturnValue.getStrReturnValue(result));
            }
        }

        /// <summary>
        ///     Cpi Payout by denomination
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_CpiPayoutByDemo_Click(object sender, EventArgs e)
        {
            if (cpiRunning && payoutRunning && ((payoutByDenomFrm == null) || (payoutByDenomFrm != null && !payoutByDenomFrm.Visible)))
            {
                payoutByDenomFrm = new frmPayoutByDenom(Payout, cpiHopper, textBox1);
                payoutByDenomFrm.Show();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void reconnectionTimer_Tick(object sender, EventArgs e)
        {
            if (sender is  System.Windows.Forms.Timer)
            {
                System.Windows.Forms.Timer t = sender as System.Windows.Forms.Timer;
                t.Enabled = false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFloat_Click(object sender, EventArgs e)
        {
            char[] currency = { 'S', 'A', 'R' };

            try
            {
                //  Validate Cpi Payout amount
                if  (tbFloatAmount.Text == "")
                    return;

                //  Parse to a float
                float fFa = float.Parse(tbFloatAmount.Text);

                int fa = (Int32)(fFa * 100); // multiply by 100 for penny value

                //  If payout selected
                cpiHopper.PayoutAmount(fa, currency);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());

                return;
            }
        }

        /// <summary>
        ///     Payout By Denomination
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPayoutByDenom_Click(object sender, EventArgs e)
        {
            if  (cpiRunning && payoutRunning && ((payoutByDenomFrm == null) || (payoutByDenomFrm != null && !payoutByDenomFrm.Visible)))
            {
                payoutByDenomFrm = new frmPayoutByDenom(Payout, cpiHopper, textBox1);
                payoutByDenomFrm.Show();
            }
        }
    }
}
